using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using OpenComposite.EII.Repository;
using WeifenLuo.WinFormsUI.Docking;
using System.Xml;
using System.IO;

namespace OpenComposite.EII.Designer.SCA
{
	public partial class FormOperations : DockContent
	{
		#region Initialization
		public FormOperations(IServiceProvider serviceProvider)
		{
			_serviceProvider = serviceProvider;

			InitializeComponent();

			init();
		}
		private void init()
		{
			this.DialogResult = DialogResult.Cancel;

			this.StartPosition = FormStartPosition.CenterScreen;
			this.DockAreas = DockAreas.Float;
			this.ShowHint = DockState.Float;
			this.TabText = "Capabilities";

			dgvOperations.AutoGenerateColumns = false;

		}
		#endregion

		#region Public Members

		#region Events
		#endregion

		#region Properties
		public bool ReadOnly
		{
			get { return _bReadonly; }
			set {
				if ( _bReadonly != value ) {
					_bReadonly = value;
					dgvOperations.AllowDrop = !_bReadonly;
					tsbtnAddNewOp.Visible = !_bReadonly;
				}
			}
		}
		public RepositoryItemBase ParentItem
		{
			get { return _parentItem; }
		}
		public Operation[] Operations
		{
			get {
				return _lstBaseOps.ToArray();
			}
		}
		#endregion

		#region Methods

		//public void Show(RepositoryItemBase parentItem)
		//{
		//    fillList(parentItem);
		//    this.Show();
		//}
		//public void Show(RepositoryItemBase parentItem, DockPanel dockPanel, Point location)
		//{
		//    fillList(parentItem);
		//    this.Show(dockPanel, new Rectangle(location, this.Size));
		//    //this.Show();
		//}
		public void Show(List<Operation> operations)
		{
			if ( operations == null )
				_lstBaseOps = new List<Operation>();
			else
				_lstBaseOps = new List<Operation>(operations);
			fillList(operations);
			this.Show();
		}
		public void Show(List<Operation> operations, DockPanel dockPanel, Point location)
		{
			if ( operations == null )
				_lstBaseOps = new List<Operation>();
			else
				_lstBaseOps = new List<Operation>(operations);
			fillList(operations);
			this.Show(dockPanel, new Rectangle(location, this.Size));
			//this.Show();
		}
		#endregion

		#endregion

		#region Protected Members

		protected override object GetService(Type service)
		{
			return _serviceProvider.GetService(service);
		}

		#endregion

		#region Private Members

		#region Variables
		private bool _bReadonly = false;

		private RepositoryItemBase _parentItem = null;
		private BindingList<OperationBind> _operations = null;
		private List<Operation> _lstBaseOps;

		private IServiceProvider _serviceProvider;
		#endregion

		#region Methods
		//private void fillList(RepositoryItemBase parentItem)
		//{
		//    _parentItem = parentItem;
		//    _operations.Clear();
		//    _operations = null;

		//    DataTable dt = Global.Data.GetRepositoryHierarchyChildRepositoryList(parentItem, ItemType.Operation);

		//    colName.DataPropertyName = "operation_nm";
		//    colInputXsd.DataPropertyName = "operation_input_bobj_nm";
		//    colOutputXsd.DataPropertyName = "operation_output_bobj_nm";
		//    colDescription.DataPropertyName = "operation_desc";

		//    dgvOperations.DataSource = dt;
		//}
		private void fillList(List<Operation> operations)
		{
			_parentItem = null;
			_operations = new BindingList<OperationBind>(operations.ConvertAll<OperationBind>(
				delegate(Operation op)
				{
					return new OperationBind(op);
				}
			));
			//_operations.AllowEdit = false;
			//_operations.AllowNew = false;
			//_operations.AllowRemove = false;

			colName.DataPropertyName = "Name";
			colInputXsd.DataPropertyName = "InputBusinessObjectName";
			colOutputXsd.DataPropertyName = "OutputBusinessObjectName";
			colDescription.DataPropertyName = "Description";

			dgvOperations.DataSource = _operations;
		}
		private void addOperation(Operation operation)
		{
			if ( _parentItem != null ) {
				throw new NotImplementedException();
			} else if ( _operations != null ) {
				_operations.Add(new OperationBind(operation));
				//_operations.ResetItem(_operations.Count - 1);
				//fillList(_operations); 
			}
		}
		private void deleteOperationBind(OperationBind operation)
		{
			if ( _parentItem != null ) {
				throw new NotImplementedException();
			} else if ( _operations != null ) {
				if ( operation.Operation.Delete(true) ) {
					_operations.Remove(operation);
					_operations.ResetBindings();
					_lstBaseOps.Remove(operation.Operation);
					//fillList(_operations);
				}
			}
		}
		private OperationBind getOperationBind(int indexRow)
		{
			if ( indexRow < 0 || indexRow >= dgvOperations.RowCount )
				return null;

			OperationBind op = null;
			object obj = dgvOperations.Rows[indexRow].DataBoundItem;
			if ( obj is DataRow ) {
				throw new NotImplementedException();
			} else if ( obj is OperationBind ) {
				op = (OperationBind)obj;
			}
			return op;
		}
		#endregion

		#region Event Handler
		private void dgvOperations_CellContentClick(object sender, DataGridViewCellEventArgs e)
		{
			if ( (e.ColumnIndex != colInputXsd.Index && e.ColumnIndex != colOutputXsd.Index )
				 || e.RowIndex < 0 )
				return;

			formXmlViewer frmXml = new formXmlViewer();
			OperationBind op = getOperationBind(e.RowIndex);
			XmlDocument xd = new XmlDocument();
			XmlWriterSettings settings = new XmlWriterSettings();
			settings.OmitXmlDeclaration = true;
			if ( e.ColumnIndex == colInputXsd.Index && op.InputBusinessObject != null ) {
				// Input Schema column
				xd.LoadXml(op.InputBusinessObject.SchemaString);
			} else if ( e.ColumnIndex == colOutputXsd.Index && op.OutputBusinessObject != null ) {
				// Output Schema column
				xd.LoadXml(op.OutputBusinessObject.SchemaString);
			}
			frmXml.XmlDocument = xd;
			frmXml.ShowDialog();
		}

		#region Drag & Drop
		private void dgvOperations_DragDrop(object sender, DragEventArgs e)
		{
			TreeNode tn = e.Data.GetData(typeof(TreeNode)) as TreeNode;
			// if not dragging an Operation object
			if ( tn == null ) {
				// drop not allowed
				e.Effect = DragDropEffects.None;
				return;
			}
			BusinessObject bo = tn.Tag as BusinessObject;
			if ( bo == null ) {
				// drop not allowed
				e.Effect = DragDropEffects.None;
				return;
			}
			Point ptClient = dgvOperations.PointToClient(new Point(e.X, e.Y));
			DataGridView.HitTestInfo hti = dgvOperations.HitTest(ptClient.X, ptClient.Y);
			OperationBind op = getOperationBind(hti.RowIndex);
			if ( op == null )
				return;
			// mouse over 'Input Schema' or 'Output Schema' column?
			if ( hti.Type == DataGridViewHitTestType.Cell ) {
				if ( hti.ColumnIndex == colInputXsd.Index ) {
					op.InputBusinessObject = bo;
					_operations.ResetItem(hti.RowIndex);
					//op.InputSchema = bo.Schema;
					//op.InputBusinessObjectId = bo.ID;
					//op.InputBusinessObjectName = bo.Name;
				} else if ( hti.ColumnIndex == colOutputXsd.Index ) {
					op.OutputBusinessObject = bo;
					_operations.ResetItem(hti.RowIndex);
					//op.OutputSchema = bo.Schema;
					//op.OutputBusinessObjectId = bo.ID;
					//op.OutputBusinessObjectName = bo.Name;
				}
				//fillList(_operations);
			}
		}

		private void dgvOperations_DragEnter(object sender, DragEventArgs e)
		{

		}

		private void dgvOperations_DragLeave(object sender, EventArgs e)
		{

		}

		private void dgvOperations_DragOver(object sender, DragEventArgs e)
		{
			TreeNode tn = e.Data.GetData(typeof(TreeNode)) as TreeNode;
			// if not dragging an Operation object
			if ( tn == null ) {
				// drop not allowed
				e.Effect = DragDropEffects.None;
				return;
			}
			BusinessObject bo = tn.Tag as BusinessObject;
			if ( bo == null ) {
				// drop not allowed
				e.Effect = DragDropEffects.None;
				return;
			}
			Point ptClient = dgvOperations.PointToClient(new Point(e.X, e.Y));
			DataGridView.HitTestInfo hti = dgvOperations.HitTest(ptClient.X, ptClient.Y);
			// mouse over 'Input Schema' or 'Output Schema' column?
			if ( hti.Type == DataGridViewHitTestType.Cell &&
				 ( hti.ColumnIndex == colInputXsd.Index || hti.ColumnIndex == colOutputXsd.Index ) ) {
				e.Effect = DragDropEffects.Move;
			} else {
				e.Effect = DragDropEffects.None;
			}
		}

		private void dgvOperations_GiveFeedback(object sender, GiveFeedbackEventArgs e)
		{

		}

		private void dgvOperations_QueryContinueDrag(object sender, QueryContinueDragEventArgs e)
		{

		}
		#endregion

		private void contextMain_Opening(object sender, CancelEventArgs e)
		{
			if ( this.ReadOnly )
				e.Cancel = true;
		}
		private void dgvOperations_MouseDown(object sender, MouseEventArgs e)
		{
		}

		private void tsmiAddNewOp_Click(object sender, EventArgs e)
		{
			RepositoryService repSvc = (RepositoryService)this.GetService(typeof(RepositoryService));
			if ( repSvc == null )
				throw new NullReferenceException("RepositoryService not available.");

			bool bSaveContinue;
			do {
				Operation op = repSvc.GetItem(ItemType.Operation, true, 0, true, out bSaveContinue) as Operation;
				if ( op != null )
					addOperation(op);
			} while ( bSaveContinue );
		}
		private void tsmiDeleteOp_Click(object sender, EventArgs e)
		{
			if ( dgvOperations.SelectedRows.Count <= 0 )
				return;
			object objsel = dgvOperations.SelectedRows[0].DataBoundItem;
			if ( objsel is DataRow ) {
				throw new NotImplementedException();
			} else if ( objsel is OperationBind ) {
				deleteOperationBind((OperationBind)objsel);
			}
		}

		private void tsbtnOK_Click(object sender, EventArgs e)
		{
			if ( _lstBaseOps == null )
				_lstBaseOps = new List<Operation>();
			_lstBaseOps.Clear();
			foreach ( OperationBind opbind in _operations ) {
				Operation op = opbind.Operation;
				op.SetInputBusinessObject(opbind.InputBusinessObject);
				op.SetOutputBusinessObject(opbind.OutputBusinessObject);
				_lstBaseOps.Add(op);
			}
			this.DialogResult = DialogResult.OK;
			this.Close();
		}

		#endregion

		#endregion


		private class OperationBind
		{
			public OperationBind(Operation op)
			{
				_op = op;
				this.Name = op.Name;
				this.Description = op.Description;
				this.InputBusinessObject = op.GetInputBusinessObject();
				this.OutputBusinessObject = op.GetOutputBusinessObject();
			}
			private Operation _op;

			public Operation Operation
			{
				get { return _op; }
			}

			private string _name;
			public string Name
			{
				get { return _name; }
				set { _name = value; }
			}
			private string _inputname;
			public string InputBusinessObjectName
			{
				get { return _inputname; }
				set { _inputname = value; }
			}
			private string _outputname;
			public string OutputBusinessObjectName
			{
				get { return _outputname; }
				set { _outputname = value; }
			}
			private string _desc;
			public string Description
			{
				get { return _desc; }
				set { _desc = value; }
			}
			private BusinessObject _boInput;
			public BusinessObject InputBusinessObject
			{
				get { return _boInput; }
				set {
					_boInput = value;
					if ( value != null )
						this.InputBusinessObjectName = value.Name;
					else
						this.InputBusinessObjectName = "";
				}
			}
			private BusinessObject _boOutput;
			public BusinessObject OutputBusinessObject
			{
				get { return _boOutput; }
				set {
					_boOutput = value;
					if ( value != null )
						this.OutputBusinessObjectName = value.Name;
					else
						this.OutputBusinessObjectName = "";
				}
			}

		}
	}
}